package com.chenfan.mcn.config;

import com.chenfan.common.annotations.DataPrivilegeCodeHandlerInterceptor;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.mcn.annotations.ActionTracing;
import com.chenfan.mcn.annotations.NoLogin;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.common.extension.context.TraceContext;
import com.chenfan.common.extension.context.TraceContextHolder;
import com.chenfan.mcn.utils.RpcUtil;
import com.chenfan.privilege.common.config.SearchAuthority;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.core.MethodParameter;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * API鉴权拦截器
 *
 * @author wulg
 * @date 2021-12-15
 **/
@Slf4j
public class AuthenticationHandlerInterceptor extends DataPrivilegeCodeHandlerInterceptor {

    private final PrivilegeClient privilegeClient;

    public AuthenticationHandlerInterceptor(PrivilegeClient privilegeClient) {
        this.privilegeClient = privilegeClient;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //排除-静态资源handler
        if(handler != null && handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = ((HandlerMethod) handler);
            //排除BasicErrorController
            if(BasicErrorController.class.isAssignableFrom(handlerMethod.getBeanType())) {
                return true;
            }
            //标记行为名称
            if(handlerMethod.hasMethodAnnotation(ActionTracing.class)) {
                ActionTracing actionTracing = handlerMethod.getMethodAnnotation(ActionTracing.class);
                TraceContextHolder.put(TraceContext.ACTION_NAME, actionTracing.value());
            }
            //排除-无须登录
            if(handlerMethod.getBeanType().isAnnotationPresent(NoLogin.class) || handlerMethod.hasMethodAnnotation(NoLogin.class)){
                return true;
            }
            //校验登录
            if(Objects.isNull(UserVoContextHolder.getUserVo())) {
                throw new BusinessException(McnErrorCode.UNAUTHORIZED);
            }
        }
        return super.preHandle(request, response, handler);
    }

    @Override
    public boolean hasSearchAuthority(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(SearchAuthority.class);
    }

    @Override
    public String getPrivilegeCode(String menuCode) {
        String privilegeCode = RpcUtil.getObjException(privilegeClient.getSearchPrivilegeCode(menuCode),"从权限中心获取数据权限标识异常");
        if(StringUtils.isBlank(privilegeCode)) {
            throw new BusinessException(McnErrorCode.NO_PRIVILEGE_CODE.code(), String.format("请仔细检查菜单【%s】&角色的数据权限配置！", menuCode));
        }
        return privilegeCode;
    }
}
